package com.ruoyi.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.exception.file.FileException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.system.domain.SysFile;
import com.ruoyi.system.domain.vo.FileRelate;
import com.ruoyi.system.mapper.SysFileMapper;
import com.ruoyi.system.service.ISysFileService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.FileUrlResource;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;


@Service
public class SysFileServiceImpl extends ServiceImpl<SysFileMapper, SysFile> implements ISysFileService {
    @Autowired
    private SysFileMapper sysFileMapper;

    /**
     * 查询系统文件
     *
     * @param id 系统文件主键
     * @return 系统文件
     */
    @Override
    public SysFile selectSysFileById(Long id)
    {
        return sysFileMapper.selectSysFileById(id);
    }

    /**
     * 查询系统文件列表
     *
     * @param sysFile 系统文件
     * @return 系统文件
     */
    @Override
    public List<SysFile> selectSysFileList(SysFile sysFile)
    {
        return sysFileMapper.selectSysFileList(sysFile);
    }

    /**
     * 新增系统文件
     *
     * @param sysFile 系统文件
     * @return 结果
     */
    @Override
    public int insertSysFile(SysFile sysFile)
    {
        sysFile.setCreateTime(DateUtils.getNowDate());
        return sysFileMapper.insertSysFile(sysFile);
    }

    /**
     * 修改系统文件
     *
     * @param sysFile 系统文件
     * @return 结果
     */
    @Override
    public int updateSysFile(SysFile sysFile)
    {
        return sysFileMapper.updateSysFile(sysFile);
    }

    /**
     * 批量删除系统文件
     *
     * @param ids 需要删除的系统文件主键
     * @return 结果
     */
    @Override
    public int deleteSysFileByIds(Long[] ids)
    {
        return sysFileMapper.deleteSysFileByIds(ids);
    }

    /**
     * 删除系统文件信息
     *
     * @param id 系统文件主键
     * @return 结果
     */
    @Override
    public int deleteSysFileById(Long id)
    {
        return sysFileMapper.deleteSysFileById(id);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public SysFile storeFile(MultipartFile file, String lx) {
        if(StringUtils.isEmpty(lx)) {
            lx = "default";
        }

        String oriFileName = StringUtils.cleanPath(file.getOriginalFilename());

        String prefix = oriFileName.substring(0, oriFileName.lastIndexOf("."));
        String suffix = oriFileName.substring(oriFileName.lastIndexOf(".") + 1);

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date1 = new Date();
        String currentTime = lx + File.separatorChar + dateFormat.format(date1) ;
        String fileName = prefix + "_" + date1.getTime() + "." + suffix;
        // 目录
        String dir = RuoYiConfig.getUploadPath() + File.separatorChar + currentTime;
        // 绝对路径
        String absPath = dir + File.separatorChar + fileName;
        // 相对路径
        String realPath = File.separatorChar + currentTime + File.separatorChar + fileName;

        Path targetLocation = Paths.get(absPath);

        if(!Files.exists(Paths.get(dir))) {
            try {
                Files.createDirectories(targetLocation);
            } catch (Exception ex) {
                ex.printStackTrace();
                throw new RuntimeException("Could not create the directory where the uploaded files will be stored.");
            }
        }

        SysFile fileEntity = new SysFile();
        fileEntity.setFileName(fileName);
        fileEntity.setOriFileName(oriFileName);
        fileEntity.setFileType(file.getContentType());
        fileEntity.setSuffix(suffix);
        fileEntity.setXtlx(lx);
        fileEntity.setUrl(realPath);
        fileEntity.setSize(file.getSize());
        fileEntity.setCreateTime(date1);

        try {
            // Check if the file's name contains invalid characters
            if(fileName.contains("..")) {
                throw new RuntimeException("Sorry! Filename contains invalid path sequence " + fileName);
            }

            // Copy file to the target location (Replacing existing file with the same name)
            Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
            save(fileEntity);

            return fileEntity;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    @Override
    public void deleteFile(Long id) {
        SysFile entity = getById(id);

        String filePath = RuoYiConfig.getUploadPath() + entity.getUrl();
        File file = new File(filePath);
        if(file.exists()) {
            file.delete();
        }
        removeById(id);
    }

    @Override
    public Resource loadFileAsResource(SysFile fileEntity) {
        String filePath = RuoYiConfig.getUploadPath()  + fileEntity.getUrl();
        try {
            Resource resource = null;
            if(fileEntity.getUrl().contains("http")) {
                filePath = fileEntity.getUrl();
                resource = new FileUrlResource(filePath);
            } else {
                resource = new FileSystemResource(filePath);
            }

            if(resource.exists()) {
                return resource;
            } else {
                throw new RuntimeException("File not found " + filePath);
            }
        } catch (Exception e) {
            throw new RuntimeException("File not found " + filePath);
        }
    }

    @Override
    public void updateRelate(FileRelate fileRelate) {
        Long[] fileId = fileRelate.getFileId();
        Long relateId = fileRelate.getRelateId();

        if(fileId != null) {
            for(Long id : fileId) {
                SysFile fileEntity = this.getById(id);
                if(fileEntity != null) {
                    fileEntity.setRelateId(relateId);
                    this.updateById(fileEntity);
                }
            }
        }
    }

    @Override
    public List<SysFile> selectSysFileListByRelateId(Long relateId, String xtlx) {
        return baseMapper.selectSysFileListByRelateId(relateId, xtlx);
    }
}
